import http from 'http';
import express, { Express } from 'express';

import cors from 'cors';
import cookieParser from 'cookie-parser';

import { ChatOllama } from '@langchain/ollama';
import { HumanMessage /**AIMessage */ } from '@langchain/core/messages';

const modelType = {
  'codegeex4:9b': 'codegeex4:9b',
  'qwen2.5-coder': 'qwen2.5-coder',
  'qwen2.5': 'qwen2.5',
};

const model = modelType['codegeex4:9b'];
const llm = new ChatOllama({ model });

//创建一个应用，注意app其实就是一个函数，类似function(req, res) {}
const app = express();
//创建一个http服务器，既然app是一个函数，那这里就可以传入。
const server = http.createServer(app);

// 设置跨域请求，使用 cors 中间件
app.use(cors());

// 从 express4.16.0 开始 express已经将部分 body-parser集成到自身的中间件之中,可以直接解析JSON数据
app.use(express.json());

// 对于前端传输的 formData 数据,需要使用express.urlencoded 解析URL编码的数据,使用 multer处理multipart/form-data中的文件数据
app.use(express.urlencoded({ extended: true }));

app.use(cookieParser());

// 这里模仿请求第三方接口，该接口接收到的是event-stream类型的流式数据，然后再流式返回给前端，前端可以用fetchEventSource库来处理数据
app.post('/chat', async (req, res) => {
  try {
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');
    res.setHeader('Content-Type', 'text/event-stream');
    res.flushHeaders(); // 确保立即发送响应头

    const { messages } = req.body;
    if (!messages) {
      res.write('请传递要问的问题');
      res.end();
    }
    const url = 'http://localhost:9999/generateText';
    const data = {
      messages,
      chatId: '66f8c8c92d714ef4dbb0b621',
    };
    // 配置Axios请求，指向第三方接口
    const response = await axios.post(url, data, {
      responseType: 'stream',
      headers: {
        charset: 'UTF-8',
        'Content-Type': 'application/json',
        Accept: 'text/event-stream',
        Authorization:
          'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NmY4YjUxZjlkMzE2YjBhNjhlYWQ4ZmQiLCJpYXQiOjE3Mjc4NDY5MTQsImV4cCI6MTcyODI3ODkxNH0.fV4HviDZPTl1bqiOSN661_kExAa9kmS2xuV7hT6HWUU',
      },
    });

    // 解析并转发第三方接口的事件流数据到客户端
    response.data.on('data', (chunk) => {
      res.write(chunk.toString());
    });

    response.data.on('end', () => {
      res.end();
    });

    response.data.on('error', (err) => {
      console.error(err);
      res.status(500).send('Error occurred while processing the stream.');
    });
  } catch (err) {
    next(err);
  }
});

// 这里模仿大模型生成文本的接口，生成的文本块（chunk）流式返回出去
server.post('/generateText', async (req, res) => {
  try {
    res.setHeader('Cache-Control', 'no-cache');
    res.setHeader('Connection', 'keep-alive');
    res.setHeader('Content-Type', 'text/event-stream');
    res.flushHeaders(); // 确保立即发送响应头

    const { messages } = req.body;
    if (!messages) {
      res.write('请传递要问的问题');
      res.end();
    }

    // 查找数据并且按照更新时间升序排序
    let data = [];
    data.push(new HumanMessage({ content: messages }));

    for await (const chunk of await llm.stream(data)) {
      if (chunk?.response_metadata?.done) {
        res.write(`data: [DONE]\n\n`);
        res.end();
      } else {
        res.write(`data: ${chunk.content}\n\n`);
      }
    }
  } catch (err) {
    next(err);
  }
});

server.listen(9999, '0.0.0.0', () => {
  console.log(`服务已启动,运行端口: http://localhost:${port}`);
});
